"""
Récupération des identifiants Accès Libre via l'API DATAtourisme
Export par type d'identifier (bordereau)
"""
# Créé par Anjou Tourisme Attractivité
# Annabelle ALLARD — annabelle-allard@anjou-tourisme.com

import requests
import json
import csv
import time
import re
from datetime import date

# ══════════════════════════════════════════════════════════════
# ⚙️  CONFIGURATION — champs à personnaliser avant de lancer
# ══════════════════════════════════════════════════════════════

# 🔑 Votre clé API DATAtourisme (fournie lors de votre inscription)
API_KEY = "VOTRE-CLÉ-API-ICI"

# 🗺️  Filtre géographique
# Pour un département  : insee[eq]=XX
# Pour plusieurs       : insee[in]=XX,YY,ZZ
# Exemples : [eq]=49 (Maine-et-Loire), [in]=44,49,53,72,85 (Pays de la Loire)
FILTER_EXPR = (
    "hasExternalReference.hasExternalPlatform.hasExternalPlatformUrl[eq]=https://acceslibre.beta.gouv.fr"
    " AND "
    "isLocatedAt.address.hasAddressCity.isPartOfDepartment.insee[eq]=XX"
)

# ══════════════════════════════════════════════════════════════
# ⛔  Ne pas modifier en dessous de cette ligne
# ══════════════════════════════════════════════════════════════

BASE_URL  = "https://api.datatourisme.fr/v1"
PAGE_SIZE = 250
PAUSE     = 0.15

TYPES_IDENTIFIER = ["ACCAM", "ASC", "HOT", "HLO", "PCU", "LOI", "RET", "HCO", "RES", "ORG", "HPA", "FMA", "DEG", "PNA", "VIL"]

DATE_PREFIX = date.today().strftime("%Y%m%d")

match = re.search(r"isPartOfDepartment\.insee\[(?:eq|in)\]=([0-9,]+)", FILTER_EXPR)
ZONE = match.group(1).replace(",", "-") if match else "inconnu"

FIELDS = ",".join([
    "uuid",
    "uri",
    "label",
    "identifier",
    "hasExternalReference",
    "hasBeenCreatedBy",
    "isLocatedAt.address.hasAddressCity",
    "isLocatedAt.address.hasAddressCity.isPartOfDepartment",
])

HEADERS = {"X-API-Key": API_KEY, "Accept": "application/json"}

# ── Helpers ───────────────────────────────────────────────────────────────────

def extract_acceslibre_id(refs) -> str | None:
    if not isinstance(refs, list):
        refs = [refs]
    for ref in refs:
        if not isinstance(ref, dict):
            continue
        platform = ref.get("hasExternalPlatform", [])
        if isinstance(platform, list):
            platform = platform[0] if platform else {}
        url = platform.get("hasExternalPlatformUrl", "")
        if "acceslibre" in url.lower():
            return ref.get("hasExternalIdentifier")
    return None


def extract_label(poi: dict) -> str:
    label = poi.get("label", {})
    if isinstance(label, dict):
        return label.get("@fr") or label.get("@en") or next(iter(label.values()), "")
    return str(label) if label else ""


def extract_commune_label(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        city = address["hasAddressCity"]
        if isinstance(city, dict):
            nom = city.get("label", {})
            if isinstance(nom, dict):
                return nom.get("@fr") or nom.get("@en", "")
            return str(nom)
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_commune_insee(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        city = address["hasAddressCity"]
        if isinstance(city, dict):
            return city.get("insee", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_departement(poi: dict) -> str:
    try:
        locations = poi.get("isLocatedAt", [])
        if not isinstance(locations, list):
            locations = [locations]
        address = locations[0]["address"]
        if isinstance(address, list):
            address = address[0]
        dept = address["hasAddressCity"]["isPartOfDepartment"]
        if isinstance(dept, list):
            dept = dept[0] if dept else {}
        return dept.get("insee", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def extract_legal_name(poi: dict) -> str:
    try:
        created_by = poi.get("hasBeenCreatedBy", {})
        if isinstance(created_by, list):
            created_by = created_by[0] if created_by else {}
        return created_by.get("legalName", "")
    except (KeyError, IndexError, TypeError):
        pass
    return ""


def build_widget(acceslibre_id: str) -> str:
    return (
        f'<div id="widget-a11y-container" data-pk="{acceslibre_id}" data-baseurl="https://acceslibre.beta.gouv.fr"></div> '
        f'<a href="#" aria-haspopup="dialog" data-erp-pk="{acceslibre_id}" aria-controls="dialog" data-owner="acceslibre">Accessibilité</a> '
        f'<script src="https://acceslibre.beta.gouv.fr/static/js/widget.js" type="text/javascript" async="true"></script>'
    )


def get_type(identifier: str) -> str | None:
    for prefix in TYPES_IDENTIFIER:
        if identifier.upper().startswith(prefix):
            return prefix
    return None

# ── Appels API ────────────────────────────────────────────────────────────────

def fetch_page(url: str, params: dict | None = None) -> dict:
    resp = requests.get(url, headers=HEADERS, params=params, timeout=30)
    resp.raise_for_status()
    return resp.json()


def fetch_all() -> list[dict]:
    params = {
        "api_key":   API_KEY,
        "fields":    FIELDS,
        "filters":   FILTER_EXPR,
        "page_size": PAGE_SIZE,
        "page":      1,
    }

    results  = []
    url      = f"{BASE_URL}/catalog"
    page_num = 0

    while url:
        page_num += 1
        print(f"  Page {page_num}…", end=" ", flush=True)

        data    = fetch_page(url, params if page_num == 1 else None)
        objects = data.get("objects", [])
        meta    = data.get("meta", {})

        if page_num == 1:
            print(f"(total : {meta.get('total', '?')} POIs, {meta.get('total_pages', '?')} pages)")

        for poi in objects:
            acceslibre_id = extract_acceslibre_id(poi.get("hasExternalReference", []))
            if acceslibre_id:
                results.append({
                    "identifier":         poi.get("identifier", ""),
                    "label":              extract_label(poi),
                    "code_insee_commune": extract_commune_insee(poi),
                    "commune":            extract_commune_label(poi),
                    "departement_insee":  extract_departement(poi),
                    "datatourisme_uuid":  poi.get("uuid", ""),
                    "datatourisme_uri":   poi.get("uri", ""),
                    "acceslibre_id":      acceslibre_id,
                    "acceslibre_url":     f"https://acceslibre.beta.gouv.fr/uuid/{acceslibre_id}/",
                    "acceslibre_widget":  build_widget(acceslibre_id),
                    "producteur":         extract_legal_name(poi),
                })

        print(f"    → {len(results)} trouvés jusqu'ici")

        url = meta.get("next")
        if url:
            time.sleep(PAUSE)

    results.sort(key=lambda x: x["identifier"].lower())
    return results

# ── Export ────────────────────────────────────────────────────────────────────

def save_csv(data: list[dict], path: str) -> None:
    if not data:
        return
    with open(path, "w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=data[0].keys(), delimiter=";", quoting=csv.QUOTE_MINIMAL)
        writer.writeheader()
        writer.writerows(data)
    print(f"  ✓ {path} ({len(data)} entrées)")


def save_by_type(data: list[dict]) -> None:
    try:
        from google.colab import files
        colab = True
    except ImportError:
        colab = False

    print(f"\n── Export CSV par bordereau ──────────────────────────────")

    buckets: dict[str, list[dict]] = {prefix: [] for prefix in TYPES_IDENTIFIER}
    autres = []

    for row in data:
        prefix = get_type(row["identifier"])
        if prefix:
            buckets[prefix].append(row)
        else:
            autres.append(row)

    for prefix, rows in buckets.items():
        if not rows:
            print(f"  – {prefix} : aucune entrée, fichier ignoré")
            continue
        path = f"{DATE_PREFIX}-AccesLibre-bordereau-{prefix}-{ZONE}.csv"
        save_csv(rows, path)
        if colab:
            files.download(path)

    if autres:
        path = f"{DATE_PREFIX}-AccesLibre-bordereau-AUTRES-{ZONE}.csv"
        print(f"  ⚠ {len(autres)} entrée(s) sans type reconnu → {path}")
        save_csv(autres, path)
        if colab:
            files.download(path)

# ── Main ──────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=" * 60)
    print(f"Récupération des IDs Accès Libre — zone : {ZONE}")
    print("Export par bordereau")
    print("Source : API DATAtourisme v1")
    print("=" * 60)

    try:
        poi_list = fetch_all()

        print(f"\n{'='*60}")
        print(f"Résultat final : {len(poi_list)} POI(s) avec un ID Accès Libre")

        if poi_list:
            save_by_type(poi_list)
        else:
            print("\nAucun résultat.")

    except requests.HTTPError as e:
        print(f"\n✗ Erreur HTTP : {e}")
    except KeyboardInterrupt:
        print("\n✗ Interrompu.")